<?php
/*
 * Caching Class
 * Written by Howard Liu <howard@ixnet.work>
 * Licensed under MIT
 */

namespace IXNetwork\Lib\Tool;

class Cache
{
    protected static $fileRoot;
    protected static $names = [];
    protected static $cacheTimes = [];
    public static $lastError;

    /**
     * Get the value of a protected member variable
     *
     * @param string $varName
     * @return null | mixed
     */
    public static function getValue($varName)
    {
        if (isset(self::$$varName)) {
            return self::$$varName;
        } else {
            return null;
        }
    }

    /**
     * Set up everything
     *
     * @param array $names
     * @param array $cacheTimes
     * @param string $fileRoot
     * @return bool|object
     */
    public static function init($names, $cacheTimes, $fileRoot = null)
    {
        self::$names = $names;
        self::$cacheTimes = $cacheTimes;
        if ($fileRoot) {
            self::$fileRoot = $fileRoot;
        } else {
            self::$fileRoot = 'Cache/';
        }
        foreach (self::$names as $name) {
            if (!file_exists(self::$fileRoot.$name)) {
                mkdir(self::$fileRoot.$name, 0777, true);
            }
        }
        return true;
    }

    /**
     * Change the return format of the data, for example, json_decode().
     * You can rewrite this method when extending this class.
     *
     * @param mixed $content
     * @return mixed
     */
    protected static function afterGet($content)
    {
        return $content;
    }

    /**
     * Check weather data is cached and get the cached data.
     *
     * @param string $name
     * @param string $cacheCode
     * @return bool|mixed
     */
    public static function get($name, $cacheCode)
    {
        if (!in_array($name, self::$names)) {
            self::$lastError = '(Error #3) The name of category cannot be found.';
            return false;
        }
        if (!key_exists($name, self::$cacheTimes)) {
            self::$lastError = '(Error #3) The name of category cannot be found.';
            return false;
        } else {
            $cacheTime = self::$cacheTimes[$name];
        }
        if (file_exists(self::$fileRoot.$name.'/'.$cacheCode)) {
            if ($cacheTime && filemtime(self::$fileRoot.$name.'/'.$cacheCode) <= time()-$cacheTime) {
                unlink(self::$fileRoot.$name.'/'.$cacheCode);
                return false;
            } else {
                return self::afterGet(file_get_contents(self::$fileRoot.$name.'/'.$cacheCode));
            }
        } else {
            return false;
        }
    }

    /**
     * Change the writing format of the data, for example, json_encode().
     * You can rewrite this method when extending this class.
     *
     * @param mixed $content
     * @return mixed
     */
    protected static function beforePut($content)
    {
        return $content;
    }

    /**
     * Write data to a file
     *
     * @param string $name
     * @param string $cacheCode
     * @param mixed $content
     * @param bool $textMode
     * @return bool
     */
    public static function put($name, $cacheCode, $content, $textMode = true)
    {
        if (!in_array($name, self::$names)) {
            self::$lastError = '(Error #3) The name of category cannot be found.';
            return false;
        } elseif (self::$cacheTimes[$name] == 0) {
            return false;
        }
        if ($textMode) {
            $file = fopen(self::$fileRoot.$name.'/'.$cacheCode, 'wt');
        } else {
            $file = fopen(self::$fileRoot.$name.'/'.$cacheCode, 'wb');
        }
        $result = fputs($file, self::beforePut($content));
        fclose($file);
        return (bool) $result;
    }
}
